package org.jackysoft.query;

import java.io.Serializable;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.ListIterator;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.util.CollectionUtils;

import com.google.common.collect.Lists;
import com.mongodb.BasicDBObjectBuilder;
import com.mongodb.DBObject;

/**
 * <dd>通用查询类
 * <dd>代表一次查询收集上来的条件 
 **/
public class Query implements Serializable{
	
	/**
	 * 
	 */
	private static final long serialVersionUID = -4194262898401166379L;

	private Log logger  = LogFactory.getLog(Query.class);
	
	protected String prefix = "a.";
	
	protected List<QueryField> fields = Lists.newArrayList();
	
	protected List<Order> orders = Lists.newArrayList();
	
	protected GroupBy groupBy = new GroupBy();
	
	protected QueryState state = QueryState.START;
	
	protected String sqlId;
	
	private String express;
	
	private boolean useCache = true;
	
	private String resultCode;
	
	
	/**
	 * 通用前缀 
	 **/
	public String getPrefix() {
		return prefix;
	}

	public void setPrefix(String prefix) {
		this.prefix = prefix;		
	}
	
	public List<QueryField> getFields() {
		return fields;
	}

	public void setFields(List<QueryField> fields) {
		this.fields = fields;
	}

	public List<Order> getOrders() {
		return orders;
	}

	public void setOrders(List<Order> orders) {
		this.orders = orders;
	}
	
	public QueryState getState() {
		return state;
	}

	public void setState(QueryState state) {
		this.state = state;
	}
	
	
	public String getSqlId() {
		return sqlId;
	}

	public void setSqlId(String sqlId) {
		this.sqlId = sqlId;
	}
	
	
	public GroupBy getGroupBy() {
		return groupBy;
	}

	public void setGroupBy(GroupBy groupBy) {
		this.groupBy = groupBy;
	}

	public String getExpress() {
		return express;
	}

	public void setExpress(String express) {
		this.express = express;
	}
	
	public boolean isUseCache() {
		return useCache;
	}

	public void setUseCache(boolean useCache) {
		this.useCache = useCache;
	}

	public String getResultCode() {
		return resultCode;
	}

	public void setResultCode(String resultCode) {
		this.resultCode = resultCode;
	}

	public String groupBy(){
		
		return this.groupBy.groupString();
	}
	
	/**
	 * 组合的最终SQL查询字符串
	 **/
	public String queryString(){
		
		if(CollectionUtils.isEmpty(fields) && CollectionUtils.isEmpty(orders))return " 1=1 ";
				
		String qs = "";
		org.jackysoft.util.CollectionUtils.filter(fields, new EmptyQueryFieldPredicate());
		ListIterator<QueryField> litr = fields.listIterator();
		
	    int size = fields.size();
		for(;litr.hasNext();){
		   QueryField qf = litr.next();
		   if(qf==null)continue;
		   if(StringUtils.isEmpty(qf.getPrefix()))
			   qf.setPrefix(this.getPrefix());
		   int nidx = litr.nextIndex();
		   if(nidx  == size){
			   qf.setNoOutOpr(true);
		   }		   
		   qs+=qf;
		}  
		if(StringUtils.isBlank(qs))qs=" 1=1 ";
				
		ListIterator<Order> oitr = orders.listIterator();
		if(orders.size()>0){
			qs+=" order by ";
			Collection<String> orderstr = Lists.newArrayList();
			for(;oitr.hasNext();){
				Order odr = oitr.next();
				if(odr==null)continue;
				orderstr.add(odr.getName()+" "+odr.getStyle());
			}
			if(orderstr.size()>0){
				qs+=StringUtils.join(orderstr, ',');
			}
		
		}
		
		
		
		return StringUtils.isEmpty(qs)?" 1=1 ":qs;
	}
	/**
	 * 组合的最终SQL查询字符串
	 **/
	public String queryString(String pf){
		
		if(CollectionUtils.isEmpty(fields) && CollectionUtils.isEmpty(orders))return " 1=1 ";
		
		String qs = "";
		org.jackysoft.util.CollectionUtils.filter(fields, new EmptyQueryFieldPredicate());
		ListIterator<QueryField> litr = fields.listIterator();
		
		int size = fields.size();
		for(;litr.hasNext();){
			QueryField qf = litr.next();
			if(qf==null)continue;
			qf.setPrefix(pf);
			int nidx = litr.nextIndex();
			if(nidx  == size){
				qf.setNoOutOpr(true);
			}		   
			qs+=qf;
		}  
		if(StringUtils.isBlank(qs))qs=" 1=1 ";
		ListIterator<Order> oitr = orders.listIterator();
		if(orders.size()>0){
			qs+=" order by ";
			Collection<String> orderstr = Lists.newArrayList();
			for(;oitr.hasNext();){
				Order odr = oitr.next();
				if(odr==null)continue;
				orderstr.add(odr.orderString(pf));
			}
			if(orderstr.size()>0){
				qs+=StringUtils.join(orderstr, ',');
			}
			
		}
		
		
		
		return StringUtils.isEmpty(qs)?" 1=1 ":qs;
	}
	
	public DBObject mongoQuery(){
		DBObject query = BasicDBObjectBuilder.start().get();
		for(QueryField qf:this.getFields()){
			query.put(qf.getName(), qf.getValue());
		}
		
		return query;
	}
	
	
	protected String httpQuery;
	public String getHttpQuery(){
		if(CollectionUtils.isEmpty(fields))return "";
		
		httpQuery = "";
		org.jackysoft.util.CollectionUtils.filter(fields, new EmptyQueryFieldPredicate());
		int i = 0;
		for(QueryField qf:fields){
			httpQuery+=String.format("query.fields[%d].inOpr=%s&",i,qf.getInOpr());
			httpQuery+=String.format("query.fields[%d].name=%s&",i,qf.getName());					
			httpQuery+=String.format("query.fields[%d].outOpr=%s&",i,qf.getOutOpr());			
			httpQuery+=String.format("query.fields[%d].value=%s&",i,qf.getValue());			
			i++;
			
		}		
		char[] chars = httpQuery.toCharArray();
		char[] nchars = Arrays.copyOfRange(chars, 0, chars.length-1);
		return new String(nchars);
	}

	
	
	public void reset(){
		prefix = "a.";
		fields = Lists.newArrayList();
		orders = Lists.newArrayList();
		groupBy = new GroupBy();
		state = QueryState.START;
		sqlId = "";
	}	
}
